package com.bby.user.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.bby.common.config.GlobalSettings;
import com.bby.common.exception.BBYException;
import com.bby.common.model.UserBusinessInfo;
import com.bby.common.model.UserCustomInfo;
import com.bby.common.model.UserPublicInfo;
import com.bby.common.model.UserSettings;
import com.bby.common.utils.R;
import com.bby.common.utils.StatusCode;
import com.bby.user.bean.*;
import com.bby.user.bean.req.*;
import com.bby.user.exception.BBYExceptionHandler;
import com.bby.user.manager.UserActionManager;
import com.bby.user.manager.UserinfoManager;
import com.bby.user.service.CaptchaService;
import com.bby.user.service.DiskService;
import com.bby.user.service.UserService;
import com.bby.user.manager.TokenManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;

@Service
public class UserServiceImpl implements UserService {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    private final UserinfoManager userinfoManager;
    private final UserActionManager userActionManager;
    private final TokenManager tokenManager;
    private final CaptchaService captchaService;
    private final DiskService diskService;


    public UserServiceImpl(UserinfoManager userinfoManager, UserActionManager userActionManager, TokenManager tokenManager, CaptchaService captchaService, DiskService diskService) {
        this.userinfoManager = userinfoManager;
        this.userActionManager = userActionManager;
        this.tokenManager = tokenManager;
        this.captchaService = captchaService;
        this.diskService = diskService;
    }

    @Override
    public LoginResult loginByCaptcha(LoginByCaptchaRequest params) throws BBYException {
        logger.debug("验证码登录:"+params);
        UserCustomInfo customInfo = userinfoManager.findUserCustomInfoByEmail(params.getEmail());
        if (ObjectUtil.isEmpty(customInfo)) {
            throw new BBYException(StatusCode.USER_NOT_FOUND,"用户名不存在！");
        }
        logger.debug("info:{}",customInfo);
        tokenManager.addLoginState(customInfo.getUserId(),params.getKeepSecond());
        return new LoginResult(new UserInfo(userinfoManager.findUserBusinessInfoById(customInfo.getUserId()),customInfo),
                tokenManager.addLoginState(customInfo.getUserId(),params.getKeepSecond()));
    }

    @Override
    public LoginResult login(LoginRequest params) throws BBYException {
        logger.debug("用户名登录:"+params);
        UserCustomInfo customInfo;
        if (Validator.isEmail(params.getAccount())){
            customInfo = userinfoManager.findUserCustomInfoByEmail(params.getAccount());
        }else {
            customInfo = userinfoManager.findUserCustomInfoByName(params.getAccount());
        }
        UserBusinessInfo businessInfo = userinfoManager.findUserBusinessInfoById(customInfo.getUserId());
        logger.debug("info:{}",customInfo);
        if ((businessInfo.getPassword()).equals(params.getPassword())){
            return new LoginResult(new UserInfo(businessInfo,customInfo),
                    tokenManager.addLoginState(customInfo.getUserId(),params.getKeepSecond()));
        }else {
           throw new BBYException(StatusCode.PASS_ERROR,"用户账号和密码不匹配！");
        }
    }

    @Override
    public void logout() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                .getRequest();
        String token = request.getHeader("token");
        logger.debug("登出：token={}",token);
        tokenManager.delLoginState(token);
    }

    @Override
    public UserInfo register(RegisterRequestParams params) throws BBYException {
        R r = captchaService.verifyCaptcha(params.getEmail(),params.getCaptcha());
        if (r==null || r.getCode()!=HttpStatus.HTTP_OK){
            throw new BBYException(StatusCode.CAPTCHA_ERROR,"验证码错误或过期！");
        }
        checkName(params.getUsername());
        checkEmail(params.email);
//            doRegisterTrans(userId,username,email,password);
        UserCustomInfo customInfo = new UserCustomInfo()
                .setEmail(params.email).setUsername(params.username);
        userinfoManager.saveCustomInfo(customInfo);
        UserBusinessInfo businessInfo = new UserBusinessInfo()
                .setUserId(customInfo.getUserId()).setPassword(params.password)
                .setScore(0).setStorageUse(0).setStorageByte(GlobalSettings.DEFAULT_STORAGE_SIZE);
        UserSettings settings = new UserSettings();
        settings.setUserId(customInfo.getUserId())
                .setBlockSearch(false)
                .setDefaultPmType("extends");
        userinfoManager.saveBusinessInfo(businessInfo);
        userActionManager.saveUserSettings(settings);
        diskService.register(customInfo.getUserId(),GlobalSettings.REGISTER_VERIFICATION);
        return new UserInfo(businessInfo,customInfo);

    }

    @Override
    public void sendMilCaptcha(String userId, String mail) throws BBYException {
        if (ObjectUtil.isEmpty(mail)){
            mail = userinfoManager.findUserCustomInfoById(userId).getEmail();
        }
        captchaService.mail(mail,"Ojknxmz5bcu7qa3qkwqu8a1sha1,.");
    }

    @Override
    public R createMailToken(String userId, String mail, String value) throws BBYException {
        if (ObjectUtil.isEmpty(mail)){
            mail = userinfoManager.findUserCustomInfoById(userId).getEmail();
        }
        return captchaService.createMailToken(mail,value);
    }

    @Override
    public void editMail(String userId, MailEditReq params) throws BBYException {
        String mail = userinfoManager.findUserCustomInfoById(userId).getEmail();
        // 先验证 token
        R r = captchaService.checkMailToken(params.getMailToken(),mail);
        if (r.getCode()!=StatusCode.OK){
            throw new BBYException(r.getCode(),r.getMsg());
        }
        // 验证新邮箱验证码
        r = captchaService.verifyCaptcha(params.getNewMail(),params.getCaptcha());
        if (r.getCode()!=StatusCode.OK){
            throw new BBYException(r.getCode(),r.getMsg());
        }
        // 修改邮箱
        userinfoManager.updateCustomInfoById(userId,"email",params.getNewMail());
    }

    @Override
    public void editPasswd(String userId, EditPasswdReq param) throws BBYException {
        String pw = userinfoManager.findUserBusinessInfoById(userId).getPassword();
        if (!pw.equals(param.getCurrentPw())){
            throw new BBYException(StatusCode.PASS_ERROR,"用户账号和密码不匹配！");
        }
        userinfoManager.updatePassword(userId,param.getNewPw());
    }

    @Override
    public void editUsername(String userId, String username) throws BBYException {
        checkName(username);
        userinfoManager.updateCustomInfoById(userId,"username",username);
    }

    @Override
    public UserPublicInfo getUserPublicInfoById(String userId) throws BBYException {
        UserCustomInfo customInfo = userinfoManager.findUserCustomInfoById(userId);
        return new UserPublicInfo(customInfo);
    }

    @Override
    public UserInfo getUserInfo(String userId) throws BBYException {
        return userinfoManager.findUserInfoById(userId);
    }

    @Override
    public List<UserPublicInfo> getUserPublicInfoByIds(List<String> ids) {
        return  userinfoManager.findUserPublicInfoByIds(ids);
    }

    @Override
    public void editCustom(String userId, String key, String value) throws BBYException {
        if (!key.matches("signature|sex|birthday")){
            throw new BBYException(StatusCode.INPUT_ERROR,"参数错误");
        }
        userinfoManager.updateCustom(userId,key,value);
    }
    //    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=12000,rollbackFor=Exception.class)
//    public void doRegisterTrans(String userId,String username,String email,String password){
//        String error="";
//        if(userInfoDao.addUserInfo(userId,username,email)==1){
//            //添加到数据库
//            if (userDao.addUserPw(userId,password)==1){
//                File userRoot = new File(ROOT_DIR,userId);
//                userRoot.mkdir();
//                if (userRoot.exists()){
//                    new File(userRoot,"labels").mkdir();
//                    new File(userRoot,"messages").mkdir();
//                }
//
//                return;
//            } else error="用户密码添加失败";
//        }else error="用户信息添加失败";
//        throw new RuntimeException(error);
//    }

    /**
     * 检查用户名
     */
    @Override
    public void checkName(String username) throws BBYException {
        if (username.matches("^([\\u4e00-\\u9fa5]{2,4})|([A-Za-z0-9_]{4,16})|([a-zA-Z0-9_\\u4e00-\\u9fa5]{3,16})$")){
            if (userinfoManager.isNameExists(username)){
                throw new BBYException(StatusCode.NAME_ERROR,"用户名已存在！");
            }
            return;
        }
        throw new BBYException(StatusCode.NAME_ERROR,"用户名不符合规范！");
    }
    @Override
    public void checkEmail(String email) throws BBYException {
        if (Validator.isEmail(email)){
            if (userinfoManager.isEmailExists(email)){
                throw new BBYException(StatusCode.MAIL_ERROR,"邮箱已存在！");
            }
            return;
        }
        throw new BBYException(StatusCode.NAME_ERROR,"邮箱不符合规范！");
    }

    //    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=12000,rollbackFor=Exception.class)
    @Override
    public boolean closeAccount(String userId) throws BBYException {
       userinfoManager.deleteBusinessInfo(userId);
       userinfoManager.deleteCustomInfo(userId);
       return true;
    }


    private void makeException(String msg){
        throw new RuntimeException(msg);
    }
}
